#ifndef __Skygen_PRS_h__
#define __Skygen_PRS_h__

#include "Core/VecMath.h"

namespace Orca {

	//--------------------------------------------------------------------------
	struct PRS {

		vec3 mPos;
		quat mRot;
		vec3 mScale;

		PRS(
			  const vec3 &pos = vec3(0.0f, 0.0f, 0.0f)
			, const quat &rot = quat(0.0f, 0.0f, 0.0f, 1.0f)
			, const vec3 &scale = vec3(1.0f, 1.0f, 1.0f) ) 
		
			: mPos(pos)
			, mRot(rot)
			, mScale(scale) {

		}

		mtx44 getMtx4() const {

			mtx44 out;

			mtx33 s;
			s.set(mScale[0], 0, 0, 0, mScale[1], 0, 0, 0, mScale[2]);
			mtx33 r; setRot(r, _getOrient() );
			mtx33 rs = r * s;

			out.set(
				  rs[0][0], rs[0][1], rs[0][2], mPos[0]
				, rs[1][0], rs[1][1], rs[1][2], mPos[1]
				, rs[2][0], rs[2][1], rs[2][2], mPos[2]
				, 0.0f, 0.0f, 0.0f, 1.0f);

			return out;
		}

		void move(const vec3 &trans) {

			mPos += _getOrient() * trans;
		}

		void yaw(float angle) {

			vec3 axis;
			axis.set(0.f, 1.f, 0.f);

			_rotate(_axisAngle(axis, angle));
		}

		void pitch(float angle) {

			vec3 axis;
			axis.set(1.f, 0.f, 0.f);

			axis = _getOrient() * axis;

			_rotate(_axisAngle(axis, angle));
		}

		void roll(float angle) {

			vec3 axis;
			axis.set(0.f, 0.f, 1.f);

			axis = _getOrient() * axis;

			_rotate(_axisAngle(axis, angle));
		}

	private:
		inline quat _getOrient() const
		{
			return mRot;
		}

		inline quat _axisAngle(const vec3& axis, float angle) {

			float halfAngle = angle * 0.5f;

			float c = cosf(halfAngle);
			float s = sinf(halfAngle);

			vec3 axis2 = axis * s;

			return quat(axis2[0], axis2[1], axis2[2], c);
		}

		inline void _rotate(const quat &quat) {

			mRot = normalize( quat *mRot  );

		}
	};

}

#endif	// __Skygen_PRS_h__